package net.ncraft.mc.easyframework.papi;

import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import net.ncraft.mc.easyframework.FunctionRegister;
import net.ncraft.mc.easyframework.context.ApplicationContext;
import net.ncraft.mc.easyframework.context.anno.Autowired;
import net.ncraft.mc.easyframework.context.anno.Component;
import net.ncraft.mc.easyframework.papi.anno.PapiParam;
import net.ncraft.mc.easyframework.papi.anno.PapiPlayer;
import net.ncraft.mc.easyframework.papi.anno.Placeholder;
import net.ncraft.mc.easyframework.papi.anno.PlaceholderController;
import org.bukkit.OfflinePlayer;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.cglib.proxy.Enhancer;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.List;

@Component
public class PlaceholderAutoRegister implements FunctionRegister {

    @Autowired
    private ApplicationContext context;

    @Override
    public void register() {
        List<Class<?>> placeholderControllers = context.getComponents().stream().filter(c -> c.isAnnotationPresent(PlaceholderController.class)).toList();

        for (Class<?> placeholderController : placeholderControllers) {
            PlaceholderController controllerAnnotation = placeholderController.getAnnotation(PlaceholderController.class);
            List<Method> placeholders = Arrays.stream(placeholderController.getMethods()).filter(m -> m.isAnnotationPresent(Placeholder.class)).toList();
            for (Method placeholder : placeholders) {

                Placeholder placeholderAnnotation = placeholder.getAnnotation(Placeholder.class);

                PlaceholderExpansion expansion = new PlaceholderExpansion() {
                    @Override
                    public @NotNull String getIdentifier() {
                        return placeholderAnnotation.identifier();
                    }

                    @Override
                    public @NotNull String getAuthor() {
                        return controllerAnnotation.author();
                    }

                    @Override
                    public @NotNull String getVersion() {
                        return controllerAnnotation.version();
                    }

                    @Override
                    public @Nullable String onRequest(OfflinePlayer player, @NotNull String params) {
                        Object[] invokeParams = new Object[placeholder.getParameterCount()];
                        for (int i = 0; i < placeholder.getParameters().length; i++) {
                            Parameter parameter = placeholder.getParameters()[i];
                            if (parameter.isAnnotationPresent(PapiPlayer.class)) {
                                if (parameter.getType().equals(OfflinePlayer.class)) {
                                    invokeParams[i] = player;
                                }
                            }
                            if (parameter.isAnnotationPresent(PapiParam.class)) {
                                if (parameter.getType().equals(String.class)) {
                                    invokeParams[i] = params;
                                }
                            }
                        }
                        try {
                            return (String) placeholder.invoke(context.getBean(placeholderController), invokeParams);
                        } catch (IllegalAccessException | InvocationTargetException e) {
                            throw new RuntimeException(e);
                        }
                    }
                };
                expansion.register();
            }

        }

    }
}
